#include "Protocol.hpp"
#include "TcpServer.hpp"
#include "Socket.hpp"

#include <unistd.h>
#include <string>
#include <ctime>
#include <memory>
#include <cstdlib>

using namespace std;
using namespace Protocol;

// ./ tcpclient ip port
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        cout << "Usage: " << argv[0] << " ip port" << endl;
        return 0;
    }
    string serverip = argv[1];
    uint16_t serverport = stoi(argv[2]);

    Net_Work::Socket *conn = new Net_Work::TcpSocket();
    if (!conn->BuildConnectSocketMethod(serverip, serverport))
    {
        cerr << "connect " << serverip << ":" << serverport << " failed" << endl;
    }
    cout << "connect " << serverip << ":" << serverport << " success" << endl;

    // std::string message = "hello world";
    // write(s->GetSocket(), message.c_str(), message.size());

    std::unique_ptr<Factory> factory(new Factory());

    srand(time(nullptr));
    std::string opers = "+-*/%^&=";
    while (true)
    {
        // 构建一个请求，遵守协议
        int x = rand() % 100;
        usleep(rand() % 7777);
        int y = rand() % 100;
        char oper = opers[rand() % opers.size()];
        std::shared_ptr<Request> req = factory->BuildRequest(x, y, oper);

        // 对请求进行序列化
        std::string requeststr;
        req->Serialize(&requeststr);

        // for test
        auto teststr = requeststr;
        teststr += " ";
        teststr += "= ";

        // 添加自描述报头
        requeststr = Encode(requeststr);    

        // 发送请求
        conn->Send(requeststr);

        std::string responsestr;
        while (true)
        {
            // 读取响应
            if (!conn->Recv(&responsestr, 1024)) break;

            // 对报文进行解析
            std::string response;
            if (!Decode(responsestr, &response))
                continue;

            // response "result code"
            auto resp = factory->BuildResponse();
            resp->Deserialize(response);

            // 计算结果
            std::cout << teststr << resp->GetResule() << "[" << resp->GetCode() << "]" << std::endl;
            break;
        }
        sleep(1);
    }

    conn->CloseSocket();

    return 0;
}